package org.example;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.example.gamemodel.World;
import org.example.service.GameServer;
import org.example.service.LoginService;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    private static LoginService loginService =new LoginService();
    private static GameServer gameServer=new GameServer();

    private static ExecutorService executorService= Executors.newFixedThreadPool(4);
    static ServerSocket serverSocket= null;
    static DatagramSocket datagramSocket=null;



    public static void main(String[] args) {
        firstStartShow();
        executorService.submit(()->{
            while (true) {
                DabugLog();
                Thread.sleep(20*1000);
            }
        });
        executorService.submit(() -> TCPAccept());
        executorService.submit(() -> UDPReceive());
    }

    private static void firstStartShow() {
        System.out.println("---TouHou Game Server---");
    }

    public static void TCPAccept(){
        try {
            serverSocket = new ServerSocket(27251);
            log("TCP Server Started.");
            while(true) {
                Socket socket = serverSocket.accept();
                InputStream inputStream=socket.getInputStream();
                byte[] bytes=new byte[1024];
                inputStream.read(bytes);
                String message=new String(bytes).trim();
                executorService.submit(()->ConsoleReback(message,socket));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void UDPReceive(){
        try {
            datagramSocket=new DatagramSocket(27252);
            byte[] receiveDate=new byte[1024];
            DatagramPacket datagramPacket=new DatagramPacket(receiveDate, receiveDate.length);
            log("UDP Server Started.");
            while(true) {
                datagramSocket.receive(datagramPacket);
                String message = new String(datagramPacket.getData(), 0, datagramPacket.getLength());
                executorService.submit(()-> Console(message));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void ConsoleReback(String message,Socket socket){
//        System.out.println("receive:"+message);
        JSONObject console_json= (JSONObject) JSON.parse(message);
        String action= (String) console_json.get("action");
        switch (action){
            case "login":{
                try {
                    String info= loginService.UserLogin((String)console_json.get("user"),(String)console_json.get("password"));
                    PrintWriter printWriter= null;
                    printWriter = new PrintWriter(socket.getOutputStream());
                    printWriter.print(info);
                    printWriter.close();
                    socket.close();
                    log(info);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                break;
            }
            case "signin":{
                try {
                    String info= loginService.UserSignIn((String)console_json.get("user"),(String)console_json.get("password"));
                    PrintWriter printWriter=new PrintWriter(socket.getOutputStream());
                    printWriter.print(info);
                    printWriter.close();
                    socket.close();
                    log(info);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                break;
            }
            case "join":{
                try{
                    String info=gameServer.PlayerJoinIn((String)console_json.get("user"),socket);
                    PrintWriter printWriter=new PrintWriter(socket.getOutputStream());
                    printWriter.print(info);
                    printWriter.flush();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            case "relink":{
                try{
                    int world_id= (int) console_json.get("world_id");
                    String info=gameServer.PlayerRelink(world_id,(String)console_json.get("user"),socket);
                    PrintWriter printWriter=new PrintWriter(socket.getOutputStream());
                    printWriter.print(info);
                    printWriter.flush();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static void Console(String message){
//        System.out.println("receive:"+message);
        JSONObject console_json= (JSONObject) JSON.parse(message);
        String action= (String) console_json.get("action");
        switch (action){
            case "send_frame":{
//                System.out.println("1");
                int world_id= (int) console_json.get("world_id");
                String user=(String) console_json.get("user");
                JSONObject frame= (JSONObject) JSON.parse(String.valueOf(console_json.get("frame")));
                gameServer.SendFrame(world_id,user,frame);
                break;
            }
        }
    }

    public static void DabugLog(){
        for(World w:gameServer.worldList) {
            System.out.println("[World_"+w.id+"]Player:"+w.player_sockets);
        }
    }

    static void log(String msg){
        System.out.println("[Main]"+msg);
    }
}